package com.example.smartpark.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.smartpark.dto.PaymentDTO;
import com.example.smartpark.dto.PaymentQueryDTO;
import com.example.smartpark.exception.BusinessException;
import com.example.smartpark.mapper.PaymentMapper;
import com.example.smartpark.mapper.ParkingRecordMapper;
import com.example.smartpark.mapper.ReservationMapper;
import com.example.smartpark.mapper.UserMapper;
import com.example.smartpark.mapper.VehicleMapper;
import com.example.smartpark.model.Payment;
import com.example.smartpark.model.ParkingRecord;
import com.example.smartpark.model.Reservation;
import com.example.smartpark.model.User;
import com.example.smartpark.service.PaymentService;
import com.example.smartpark.service.ParkingRecordService;
import com.example.smartpark.service.ReservationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 支付服务实现类
 */
@Slf4j
@Service
public class PaymentServiceImpl extends ServiceImpl<PaymentMapper, Payment> implements PaymentService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private ParkingRecordMapper parkingRecordMapper;

    @Autowired
    private ReservationMapper reservationMapper;

    @Autowired
    private VehicleMapper vehicleMapper;

    @Autowired
    private ParkingRecordService parkingRecordService;

    @Autowired
    private ReservationService reservationService;

    @Override
    public IPage<PaymentDTO> getPaymentPage(PaymentQueryDTO queryDTO) {
        // 构建分页对象
        Page<Payment> page = new Page<>(queryDTO.getPage(), queryDTO.getSize());

        // 构建查询条件
        LambdaQueryWrapper<Payment> queryWrapper = new LambdaQueryWrapper<>();
        
        // 添加查询条件
        if (queryDTO.getUserId() != null) {
            queryWrapper.eq(Payment::getUserId, queryDTO.getUserId());
        }
        
        if (queryDTO.getOrderNumber() != null && !queryDTO.getOrderNumber().isEmpty()) {
            queryWrapper.eq(Payment::getOrderNumber, queryDTO.getOrderNumber());
        }
        
        if (queryDTO.getPaymentType() != null) {
            queryWrapper.eq(Payment::getPaymentType, queryDTO.getPaymentType());
        }
        
        if (queryDTO.getPaymentMethod() != null) {
            queryWrapper.eq(Payment::getPaymentMethod, queryDTO.getPaymentMethod());
        }
        
        if (queryDTO.getMinAmount() != null) {
            queryWrapper.ge(Payment::getAmount, queryDTO.getMinAmount());
        }
        
        if (queryDTO.getMaxAmount() != null) {
            queryWrapper.le(Payment::getAmount, queryDTO.getMaxAmount());
        }
        
        if (queryDTO.getStatus() != null) {
            queryWrapper.eq(Payment::getStatus, queryDTO.getStatus());
        }
        
        if (queryDTO.getTransactionId() != null && !queryDTO.getTransactionId().isEmpty()) {
            queryWrapper.eq(Payment::getTransactionId, queryDTO.getTransactionId());
        }
        
        if (queryDTO.getPayTimeBegin() != null) {
            queryWrapper.ge(Payment::getPayTime, queryDTO.getPayTimeBegin());
        }
        
        if (queryDTO.getPayTimeEnd() != null) {
            queryWrapper.le(Payment::getPayTime, queryDTO.getPayTimeEnd());
        }
        
        if (queryDTO.getCreatedAtBegin() != null) {
            queryWrapper.ge(Payment::getCreatedAt, queryDTO.getCreatedAtBegin());
        }
        
        if (queryDTO.getCreatedAtEnd() != null) {
            queryWrapper.le(Payment::getCreatedAt, queryDTO.getCreatedAtEnd());
        }
        
        // 添加排序条件（按创建时间降序）
        queryWrapper.orderByDesc(Payment::getCreatedAt);
        
        // 执行分页查询
        IPage<Payment> paymentPage = this.page(page, queryWrapper);
        
        // 获取所有支付记录的用户ID
        List<Integer> userIds = paymentPage.getRecords().stream()
                .map(Payment::getUserId)
                .distinct()
                .collect(Collectors.toList());
        
        // 批量查询用户信息
        final Map<Integer, User> userMap = new HashMap<>();
        if (!userIds.isEmpty()) {
            LambdaQueryWrapper<User> userWrapper = new LambdaQueryWrapper<>();
            userWrapper.in(User::getId, userIds);
            List<User> users = userMapper.selectList(userWrapper);
            userMap.putAll(users.stream().collect(Collectors.toMap(User::getId, user -> user)));
        }
        
        // 转换为DTO，使用已查询的用户信息
        IPage<PaymentDTO> dtoPage = paymentPage.convert(payment -> convertToDTO(payment, userMap.get(payment.getUserId())));
        
        return dtoPage;
    }

    @Override
    public PaymentDTO getPaymentById(Long id) {
        // 查询支付记录
        Payment payment = this.getById(id);
        if (payment == null) {
            throw new BusinessException("支付记录不存在");
        }
        
        // 查询用户信息
        User user = userMapper.selectById(payment.getUserId());
        
        // 转换为DTO
        return convertToDTO(payment, user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PaymentDTO createPayment(PaymentDTO paymentDTO) {
        // 验证支付类型
        if (paymentDTO.getPaymentType() != 0 && paymentDTO.getPaymentType() != 1) {
            throw new BusinessException("无效的支付类型");
        }
        
        // 验证支付金额
        if (paymentDTO.getAmount() == null || paymentDTO.getAmount().doubleValue() <= 0) {
            throw new BusinessException("支付金额必须大于0");
        }
        
        // 验证关联记录是否存在
        if (paymentDTO.getRecordId() == null) {
            throw new BusinessException("关联记录ID不能为空");
        }
        
        // 根据支付类型处理关联记录
        if (paymentDTO.getPaymentType() == 0) { // 停车费
            ParkingRecord parkingRecord = parkingRecordMapper.selectById(paymentDTO.getRecordId());
            if (parkingRecord == null) {
                throw new BusinessException("停车记录不存在");
            }
            
            // 验证停车记录状态
            if (parkingRecord.getStatus() != 1) { // 1表示已完成
                throw new BusinessException("停车记录未完成，不能支付");
            }
            
            // 验证是否已支付
            if (parkingRecord.getIsPaid() == 1) {
                throw new BusinessException("该停车记录已支付");
            }
            
            // 设置用户ID
            paymentDTO.setUserId(parkingRecord.getVehicleId() != null ? 
                    vehicleMapper.selectById(parkingRecord.getVehicleId()).getUserId() : null);
            
        } else { // 预约费
            Reservation reservation = reservationMapper.selectById(paymentDTO.getRecordId());
            if (reservation == null) {
                throw new BusinessException("预约记录不存在");
            }
            
            // 验证预约状态
            if (reservation.getStatus() != 1) { // 1表示已确认
                throw new BusinessException("预约未确认，不能支付");
            }
            
            // 验证是否已支付
            if (reservation.getIsPaid() == 1) {
                throw new BusinessException("该预约已支付");
            }
            
            // 设置用户ID
            paymentDTO.setUserId(reservation.getUserId());
        }
        
        // 创建支付记录
        Payment payment = new Payment();
        BeanUtils.copyProperties(paymentDTO, payment);
        
        // 生成订单编号
        payment.setOrderNumber(generateOrderNumber());
        
        // 设置初始状态为待支付
        payment.setStatus(0);
        
        // 保存支付记录
        this.save(payment);

        // 更新关联记录
        updateRelatedRecord(payment);
        
        // 查询用户信息
        User user = userMapper.selectById(payment.getUserId());
        
        // 返回DTO
        return convertToDTO(payment, user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PaymentDTO completePayment(Long id, String transactionId) {
        // 查询支付记录
        Payment payment = this.getById(id);
        if (payment == null) {
            throw new BusinessException("支付记录不存在");
        }
        
        // 验证支付状态
        if (payment.getStatus() != 0) {
            throw new BusinessException("支付状态不正确，只有待支付状态可以完成支付");
        }

        // 验证支付方式是否为空
        if (payment.getPaymentMethod() == null) {
            throw new BusinessException("支付方式不能为空");
        }

        // 如果是余额支付，需要检查并扣减用户余额
        if (payment.getPaymentMethod() == 3) {
            User user = userMapper.selectById(payment.getUserId());
            if (user == null) {
                throw new BusinessException("用户不存在");
            }

            // 检查余额是否充足
            BigDecimal balance = user.getBalance() != null ? user.getBalance() : BigDecimal.ZERO;
            if (balance.compareTo(payment.getAmount()) < 0) {
                throw new BusinessException("账户余额不足");
            }

            // 扣减余额
            user.setBalance(balance.subtract(payment.getAmount()));
            user.setUpdatedAt(new Date());
            userMapper.updateById(user);
        }
        // 其他支付方式（支付宝、微信、银行卡）直接标记为支付成功
        else if (payment.getPaymentMethod() >= 0 && payment.getPaymentMethod() <= 2) {
            // 不需要处理余额，直接继续处理
            log.info("使用第三方支付方式：{}", getPaymentMethodDesc(payment.getPaymentMethod()));
        } else {
            throw new BusinessException("无效的支付方式");
        }
        
        // 更新支付记录
        payment.setStatus(1); // 1表示已支付
        payment.setTransactionId(transactionId);
        payment.setPayTime(new Date());
        this.updateById(payment);
        
        // 更新关联记录
        updateRelatedRecord(payment);
        
        // 查询用户信息
        User user = userMapper.selectById(payment.getUserId());
        
        // 返回DTO
        return convertToDTO(payment, user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PaymentDTO cancelPayment(Long id, String remark) {
        // 查询支付记录
        Payment payment = this.getById(id);
        if (payment == null) {
            throw new BusinessException("支付记录不存在");
        }
        
        // 验证支付状态
        if (payment.getStatus() != 0) {
            throw new BusinessException("支付状态不正确，只有待支付状态可以取消");
        }
        
        // 更新支付记录
        payment.setStatus(3); // 3表示已取消
        payment.setRemark(remark);
        this.updateById(payment);
        
        // 查询用户信息
        User user = userMapper.selectById(payment.getUserId());
        
        // 返回DTO
        return convertToDTO(payment, user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PaymentDTO refundPayment(Long id, String remark) {
        // 查询支付记录
        Payment payment = this.getById(id);
        if (payment == null) {
            throw new BusinessException("支付记录不存在");
        }
        
        // 验证支付状态
        if (payment.getStatus() != 1) {
            throw new BusinessException("支付状态不正确，只有已支付状态可以退款");
        }
        
        // 更新支付记录
        payment.setStatus(2); // 2表示已退款
        payment.setRemark(remark);
        this.updateById(payment);
        
        // 更新关联记录（取消已支付状态）
        if (payment.getPaymentType() == 0) { // 停车费
            // 查找关联的停车记录
            LambdaQueryWrapper<ParkingRecord> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ParkingRecord::getPaymentId, payment.getId().intValue());
            ParkingRecord parkingRecord = parkingRecordMapper.selectOne(queryWrapper);
            if (parkingRecord != null && parkingRecord.getIsPaid() == 1) {
                parkingRecord.setIsPaid(0);
                parkingRecord.setPaymentId(null);
                parkingRecordMapper.updateById(parkingRecord);
            }
        } else { // 预约费
            // 查找关联的预约记录
            LambdaQueryWrapper<Reservation> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Reservation::getPaymentId, payment.getId().intValue());
            Reservation reservation = reservationMapper.selectOne(queryWrapper);
            if (reservation != null && reservation.getIsPaid() == 1) {
                reservation.setIsPaid(0);
                reservation.setPaymentId(null);
                reservationMapper.updateById(reservation);
            }
        }
        
        // 如果是余额支付，需要退还用户余额
        if (payment.getPaymentMethod() != null && payment.getPaymentMethod() == 3) {
            User user = userMapper.selectById(payment.getUserId());
            if (user != null) {
                // 退还余额
                BigDecimal balance = user.getBalance() != null ? user.getBalance() : BigDecimal.ZERO;
                user.setBalance(balance.add(payment.getAmount()));
                user.setUpdatedAt(new Date());
                userMapper.updateById(user);
            }
        }
        
        // 查询用户信息
        User user = userMapper.selectById(payment.getUserId());
        
        // 返回DTO
        return convertToDTO(payment, user);
    }

    @Override
    public PaymentDTO getPaymentByOrderNumber(String orderNumber) {
        // 构建查询条件
        LambdaQueryWrapper<Payment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Payment::getOrderNumber, orderNumber);
        
        // 查询支付记录
        Payment payment = this.getOne(queryWrapper);
        if (payment == null) {
            throw new BusinessException("支付记录不存在");
        }
        
        // 查询用户信息
        User user = userMapper.selectById(payment.getUserId());
        
        // 转换为DTO
        return convertToDTO(payment, user);
    }

    /**
     * 生成订单编号
     * 
     * @return 订单编号
     */
    private String generateOrderNumber() {
        return System.currentTimeMillis() + UUID.randomUUID().toString().replace("-", "").substring(0, 8);
    }

    /**
     * 更新关联记录
     * 
     * @param payment 支付记录
     */
    private void updateRelatedRecord(Payment payment) {
        if (payment.getRecordId() == null) {
            log.warn("支付记录{}没有关联的记录ID", payment.getId());
            return;
        }
        
        try {
            if (payment.getPaymentType() == 0) { // 停车费
                ParkingRecord record = parkingRecordMapper.selectById(payment.getRecordId());
                if (record != null) {
                    record.setIsPaid(1); // 1表示已支付
                    record.setPaymentId(payment.getId().intValue());
                    parkingRecordMapper.updateById(record);
                    log.info("更新停车记录支付状态：recordId={}, paymentId={}", record.getId(), payment.getId());
                } else {
                    log.warn("未找到对应的停车记录：recordId={}", payment.getRecordId());
                }
            } else { // 预约费
                Reservation reservation = reservationMapper.selectById(payment.getRecordId());
                if (reservation != null) {
                    reservation.setIsPaid(1); // 1表示已支付
                    reservation.setPaymentId(payment.getId().intValue());
                    reservationMapper.updateById(reservation);
                    log.info("更新预约记录支付状态：recordId={}, paymentId={}", reservation.getId(), payment.getId());
                } else {
                    log.warn("未找到对应的预约记录：recordId={}", payment.getRecordId());
                }
            }
        } catch (Exception e) {
            log.error("更新关联记录失败：paymentId={}, recordId={}", payment.getId(), payment.getRecordId(), e);
            throw new BusinessException("更新关联记录失败：" + e.getMessage());
        }
    }

    /**
     * 将实体转换为DTO
     *
     * @param payment 支付记录实体
     * @param user 用户信息（可以为null）
     * @return 支付记录DTO
     */
    private PaymentDTO convertToDTO(Payment payment, User user) {
        if (payment == null) {
            return null;
        }
        
        PaymentDTO dto = new PaymentDTO();
        BeanUtils.copyProperties(payment, dto);
        
        // 转换字段名称以匹配前端期望的格式
        dto.setOrderNumber(payment.getOrderNumber());
        dto.setPaymentType(payment.getPaymentType());
        dto.setPaymentMethod(payment.getPaymentMethod());
        dto.setPayTime(payment.getPayTime());
        dto.setCreatedAt(payment.getCreatedAt());
        
        // 设置支付类型描述
        dto.setPaymentTypeText(getPaymentTypeDesc(payment.getPaymentType()));
        
        // 设置支付方式描述
        dto.setPaymentMethodText(getPaymentMethodDesc(payment.getPaymentMethod()));
        
        // 设置状态描述
        dto.setStatusText(getStatusDesc(payment.getStatus()));
        
        // 设置用户信息
        if (user != null) {
            dto.setUsername(user.getUsername());
            dto.setRealName(user.getRealName());
        }
        
        return dto;
    }

    /**
     * 获取支付类型描述
     *
     * @param paymentType 支付类型
     * @return 支付类型描述
     */
    private String getPaymentTypeDesc(Integer paymentType) {
        if (paymentType == null) {
            return "未知";
        }
        
        switch (paymentType) {
            case 0:
                return "停车费";
            case 1:
                return "预约费";
            default:
                return "未知";
        }
    }

    /**
     * 获取支付方式描述
     *
     * @param paymentMethod 支付方式
     * @return 支付方式描述
     */
    private String getPaymentMethodDesc(Integer paymentMethod) {
        if (paymentMethod == null) {
            return "未知";
        }
        
        switch (paymentMethod) {
            case 0:
                return "支付宝";
            case 1:
                return "微信";
            case 2:
                return "银行卡";
            case 3:
                return "余额";
            default:
                return "未知";
        }
    }

    /**
     * 获取状态描述
     *
     * @param status 状态
     * @return 状态描述
     */
    private String getStatusDesc(Integer status) {
        if (status == null) {
            return "未知";
        }
        
        switch (status) {
            case 0:
                return "待支付";
            case 1:
                return "已支付";
            case 2:
                return "已退款";
            case 3:
                return "已取消";
            default:
                return "未知";
        }
    }

    @Override
    public Map<String, Object> getPaymentStatistics() {
        Map<String, Object> statistics = new HashMap<>();
        
        // 获取今日日期范围
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        Date todayStart = calendar.getTime();
        
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        Date todayEnd = calendar.getTime();
        
        // 查询今日支付总数和金额
        LambdaQueryWrapper<Payment> todayQuery = new LambdaQueryWrapper<>();
        todayQuery.between(Payment::getPayTime, todayStart, todayEnd)
                .eq(Payment::getStatus, 1); // 已支付状态
        
        List<Payment> todayPayments = this.list(todayQuery);
        int todayCount = todayPayments.size();
        BigDecimal todayAmount = todayPayments.stream()
                .map(Payment::getAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        
        // 查询各支付方式的使用次数
        Map<String, Long> methodCounts = new HashMap<>();
        for (Payment payment : todayPayments) {
            Integer method = payment.getPaymentMethod();
            String methodKey = method != null ? method.toString() : "unknown";
            methodCounts.merge(methodKey, 1L, Long::sum);
        }
        
        // 查询各支付类型的金额统计
        Map<String, BigDecimal> typeAmounts = new HashMap<>();
        for (Payment payment : todayPayments) {
            Integer type = payment.getPaymentType();
            String typeKey = type != null ? type.toString() : "unknown";
            typeAmounts.merge(typeKey, payment.getAmount(), BigDecimal::add);
        }
        
        // 组装统计数据
        statistics.put("todayCount", todayCount);
        statistics.put("todayAmount", todayAmount);
        statistics.put("methodCounts", methodCounts);
        statistics.put("typeAmounts", typeAmounts);
        
        // 获取支付方式名称映射
        Map<String, String> methodNames = new HashMap<>();
        methodNames.put("0", "支付宝");
        methodNames.put("1", "微信");
        methodNames.put("2", "银行卡");
        methodNames.put("3", "余额");
        methodNames.put("unknown", "未知");
        statistics.put("methodNames", methodNames);
        
        // 获取支付类型名称映射
        Map<String, String> typeNames = new HashMap<>();
        typeNames.put("0", "停车费");
        typeNames.put("1", "预约费");
        typeNames.put("unknown", "未知");
        statistics.put("typeNames", typeNames);
        
        return statistics;
    }

    @Override
    public void updatePaymentMethod(Long id, Integer paymentMethod) {
        // 验证支付方式是否有效
        if (paymentMethod == null) {
            throw new BusinessException("请选择支付方式");
        }
        if (paymentMethod < 0 || paymentMethod > 3) {
            throw new BusinessException("无效的支付方式");
        }

        // 查询支付记录
        Payment payment = this.getById(id);
        if (payment == null) {
            throw new BusinessException("支付记录不存在");
        }

        // 验证支付状态
        if (payment.getStatus() != 0) {
            throw new BusinessException("支付状态不正确，只有待支付状态可以修改支付方式");
        }

        // 更新支付方式
        payment.setPaymentMethod(paymentMethod);
        payment.setUpdatedAt(new Date());
        this.updateById(payment);
    }
} 